/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once


#include <向量.h>
#include <矩阵.h>
#include <线性代数/变换.h>

#include "系统/多线程.h"
#include "S_Object.h"


#include <set>







typedef enum {
	e_车轮_前左 = 0,
	e_车轮_前右 = 1,
	e_车轮_后左 = 2,
	e_车轮_后右 = 3,

	e_车轮_后左1 = 4,
	e_车轮_后右2 = 5,
	e_车轮_后左3 = 6,
	e_车轮_后右4 = 7,

}E_车轮ID;

typedef enum {
	e_车轮MASK_前左 = 1 << 0,
	e_车轮MASK_前右 = 1 << 1,
	e_车轮MASK_后左 = 1 << 2,
	e_车轮MASK_后右 = 1 << 3,

	e_车轮MASK_后左1 = 1 << 4,
	e_车轮MASK_后右2 = 1 << 5,
	e_车轮MASK_后左3 = 1 << 6,
	e_车轮MASK_后右4 = 1 << 7,

}E_车轮MASK;


/*typedef enum {
	e_物理_None,

	e_FleX_流体,
	e_FleX_刚体,
	e_FleX_布料,
	e_FleX_柔体,

	e_Px_静态,
	e_刚体,
	e_Px_柔体,
	e_Px_布料,
	e_Px_车体,
	e_Px_车轮,
}E_物理类型;*/



//Tire types.
enum {
	TIRE_TYPE_WETS = 0,
	TIRE_TYPE_SLICKS,
	TIRE_TYPE_ICE,
	TIRE_TYPE_MUD,
	MAX_NUM_TIRE_TYPES
};

typedef enum : uint32 {
	e_phyCache_重播,
	e_phyCache_模块,
	e_phyCache_粒子,
}E_物理缓存方式;




struct S_物理材质 : public S_Object {
	virtual void*	f_get物理材质数据() = 0;
	virtual void	f_set物理材质数据(void* data) = 0;

	S_物理材质() : S_Object(E_物体类型::t_空) {}
};

//typedef struct S_三角Mesh;


typedef struct {
	void*		物体A;
	void*		物体B;
	vec3		坐标A;
	vec3		坐标B;
	float32		速度A;
	float32		速度B;
	float32		距离;
	float32		冲量;
	int32		周期;
}S_碰撞信息;

typedef bool(*fun_物理碰撞回调_p)(const S_碰撞信息& info);
//typedef float32(*fun_物理碰撞回调_p)(const S_结构对象指针 A);

/*struct S_物理几何 : public S_Object {
	E_物理类型		m_Type;


	S_物理体(uint32 key = 0);
	~S_物理体();

	//void				f_绑定user到物理体上(void* data);
	static S_物理体* f_get(uint32 key);

	virtual void* f_getBody() { return 0; }
	virtual void* f_get关联对象() { return 0; }

	virtual void		f_绑定关联对象(void* data) { ; }

	virtual void		f_setLocRot(const vec3& l, const vec3& r) {}
	virtual void		f_setVel(const vec3& l) {}

};*/

struct S_车辆 : public S_物理体 {
	vec3		m_射线碰撞点[10];


	virtual void f_加速(const float32 s) = 0;
	virtual void f_倒车(const float32 s) = 0;
	virtual void f_刹车(const float32 s) = 0;
	virtual void f_手刹(const float32 s) = 0;
	virtual void f_转向(const float32 s) = 0;


	virtual void f_加速(const bool c) {};
	virtual void f_倒车(const bool c) {};
	virtual void f_刹车(const bool c) {};
	virtual void f_手刹(const bool c) {};
	virtual void f_转向(const int8 c) {};

	virtual void f_加减档(const int8 c) {};


	virtual vec4 f_get速度() = 0;

	S_车辆():S_物理体(nullptr){}
};

typedef std::list<S_车辆*> 车辆容器_t;



struct S_Physics : public S_Object {
	E_物理引擎			m_IdType;
	vec3				m_重力;
	float32				m_步进时间;
	float32				m_粒子半径;
	int64				m_步进ID;
	uint64				m_Key;
	bool				m_是否初始化;
	bool				m_参数改变;
	std::string			m_XML;
	std::string			m_XML_asset;
	std::wstring		m_Name;


	std::filesystem::path	m_缓存路径;
	std::u16string			m_缓存文件名称;
	ivec2					m_缓存区间;
	

	fun_物理碰撞回调_p	m_全局碰撞回调;
	fun_物体async_p		mf_车辆操作更新;


	S_设备环境			m_设备;


	std::map<std::u16string, struct S_Object*> m_流入;
	std::map<std::u16string, struct S_Object*> m_流体;
	std::map<std::u16string, struct S_Object*> m_刚体;
	std::map<std::u16string, struct S_Object*> m_静态;

	std::vector<uint8> m_缓存帧标记;

	virtual void	f_Update() = 0;
	virtual void	f_应用物理变换() {}
	
	S_Physics(uint32 key = -1) : S_Object(E_物体类型::t_物体包, key), m_IdType(E_物理引擎::E_物理引擎_Mujoco) {
		m_重力 = {0.0f, -9.8f, 0.0f};
		m_步进时间 = 1.0f / 60.0f;
		m_全局碰撞回调 = NULL;
		m_粒子半径 = 0.5f;

		mf_车辆操作更新 = 0;
		m_步进ID = -1;
		m_Key = 0xffffffffffffffff;
		m_是否初始化 = true;
		m_参数改变 = true;
	}
	virtual ~S_Physics() {};


	virtual void	f_取更新物体(std::vector<std::vector<Mat44f>>& mat, std::vector<std::vector<void*>>& userData){}
	virtual void	f_取更新物体(std::vector<Mat44f>& mat, std::vector<void*>& userData) {}
	virtual void	f_等待更新结束() {}
	//S_Object*	f_get(uint32 key);
	virtual void	f_创建物理平面(vec4 location, uint32 key) {}
	virtual void	f_add刚体(S_物理体* body, uint32 scene_key) {}

	virtual void	f_添加物理体(S_物理体* body, uint32 scenekey) {}
	virtual void	f_移除物理体(S_物理体* body, uint32 scenekey) {}
	//virtual void	f_销毁物理体(S_物理体* body) {}
	virtual void	f_添加物理体碰撞回调(S_物理体* body, uint32 scenekey){}
	virtual void	f_重置变换(bool 解算 = false);


	virtual S_域区*	f_get域属性() { return {}; }
	virtual float32	f_getR() { return 0; }
	virtual uint64	f_getID() { return 0; }
	//virtual void	f_重置所有() {}
	//virtual void	f_重置() {}

	virtual void	f_get粒子坐标(uint32 id, std::vector<vec3>& particle) {}
	virtual void	f_get粒子速度(uint32 id, std::vector<float32>& speed) {}
	virtual void	f_get粒子大小(uint32 id, std::vector<float32>& size) {}


	virtual void f_Save(FILE* f) { }
	virtual void f_Load(FILE* f) { }

};

struct S_PhyVehicle {
	virtual void f_update(float32 dt) {}
};




/*namespace physx {

class PxDefaultCpuDispatcher;
class PxCudaContextManager;
class PxPBDParticleSystem;
class PxParticleBuffer;

class PxCookingParams;
class PxPBDMaterial;
class PxFoundation;
class PxRigidDynamic;
class PxRigidBody;
class PxMaterial;
class PxGeometry;
class PxPhysics;
class PxScene;
class PxActor;

namespace vehicle2
{
struct PxVehicleSuspensionForceParams;
struct PxVehicleSuspensionParams;
struct PxVehicleTireForceParams;
struct PxVehicleWheelParams;
}

}*/

//struct S_PhyWheel {
//	physx::vehicle2::PxVehicleWheelParams*	m_params;
//	physx::vehicle2::PxVehicleSuspensionParams* m_suspensionParams;
//	physx::vehicle2::PxVehicleSuspensionForceParams* m_suspensionForceParams;
//	physx::vehicle2::PxVehicleTireForceParams* m_tireForceParams;
//	physx::PxGeometry* m_geom;
//
//	float32 m_悬挂弹簧力;
//	float32 m_悬挂阻尼;
//};
//
//struct S_PxAxleParams {
//	std::vector<std::vector<uint32>> m_车轴包含车轮ID;
//	std::vector<float32> m_两轴距离;
//	std::vector<float32> m_两轮之间距离;
//};
//
//struct S_PhyVehicleParams {
//	const physx::PxGeometry* m_geom;
//	physx::PxRigidBody* m_车身刚体;
//
//	vec3 m_local;
//	vec4 m_pose;
//
//	float32 m_车重;
//	vec3 m_惯性矩;
//
//};

struct S_VehicleCommand {
	float32 m_刹车;
	float32 m_手刹;
	float32 m_油门;
	float32 m_转向;
	int32 m_挡位;
	float32 m_持续时间;
};

struct S_VehiclePowertrain {
	float32 m_惯性力矩;
	float32 m_最大扭矩;
	float32 m_怠速转速;
	float32 m_最大转速;
	float32 m_转速阻尼;
	float32 m_结合阻尼;
	float32 m_分离阻尼;
};

//struct S_PxSuspensionParams {
//	std::vector<physx::vehicle2::PxVehicleSuspensionParams> m_悬挂属性;
//};
//using u_悬挂属性 = std::vector<physx::vehicle2::PxVehicleSuspensionParams>;
//
//
//struct S_PxPhy {
//	physx::PxDefaultCpuDispatcher* m_CpuDispatcher;
//};
//
//struct S_PxScene {
//	physx::PxCudaContextManager* m_GPUCext;
//	physx::PxScene* m_Scene;
//	std::map<const physx::PxPBDParticleSystem*, physx::PxParticleBuffer*> m_粒子缓存;
//	std::vector<S_PhyVehicle*> m_车辆管理;
//	
//};
//
//struct S_Px物理引擎管理 {
//	static physx::PxFoundation* gFoundation;
//	static physx::PxPhysics* gPhysics;
//
//	static physx::PxMaterial* gPxMaterial;
//	static physx::PxPBDMaterial* gPxPBDMaterial;
//	static physx::PxCookingParams* gPxParams;
//
//	static std::map<uint16_t, S_PxPhy> gDispatcher;
//	
//	static std::map<std::string, S_PxScene> g场景环境;
//
//	S_Px物理引擎管理();
//	virtual ~S_Px物理引擎管理();
//
//	static physx::PxPhysics* f_getPhy();
//	static physx::PxCookingParams& f_getParams();
//	static S_PxPhy f_创建环境(uint16 线程数);
//	static int16_t f_分配新环境();
//	static void f_重置环境(const int16 key, const uint16 线程数);
//	static void f_删除环境(const int16 key);
//
//	static void f_创建GPU场景环境(S_PxScene& scene);
//	static void f_释放场景环境(int16 keyName);
//	static int16 f_分配场景环境();
//
//	static S_PxScene* f_创建场景对象(const std::string& 场景, int32 设备ID, const vec3& 重力);
//};





typedef struct {
	vec3					m_位置;
	vec3					m_悬挂压缩方向;


	float32					m_重量;
	float32					m_半径;
	uint32					m_精度;
	float32					m_惯性力矩;
	float32					m_轮胎宽度;
	float32					m_手刹强度;

	float32					m_最大转向角度;
	float32					m_静止状态外倾角;
	float32					m_最大下垂外倾角;
	float32					m_最大压缩外倾角;

	float32					m_悬挂刚度;
	float32					m_悬挂阻尼;
	float32					m_悬挂压缩;

	float32					m_轮胎摩擦;
	float32					m_旋转影响;



	E_车轮ID				m_安放方位;
	S_物理体*				m_车轮物理体;
}S_车轮参数;

typedef struct {
	vec3					m_位置;
	vec3					m_底盘边界;
	vec3					m_惯性力矩;
	vec3					m_重心偏移;

	float32					m_底盘重量;
	float32					m_引擎_最大扭矩;
	float32					m_引擎_最大转速;
	float32					m_变速_换挡时间;
	float32					m_离合器强度;


	S_物理体*				m_车体刚体;
	//S_物理几何体**			m_车体物理体;
	S_物理材质**			m_车体材质;
	//uint32					m_车体部件数量;

	S_车轮参数*				m_车轮;
	uint32					m_车轮数量;
}S_车体参数;


void f_init车轮参数(S_车轮参数& c);


typedef struct {
	uvec2					m_区间;
	vec3					m_悬挂压缩方向;


	float32					m_重量;
	float32					m_半径;
	uint32					m_精度;
	float32					m_惯性力矩;
	float32					m_轮胎宽度;
	float32					m_手刹强度;

	float32					m_最大转向角度;
	float32					m_静止状态外倾角;
	float32					m_最大下垂外倾角;
	float32					m_最大压缩外倾角;

	float32					m_悬挂刚度;
	float32					m_悬挂阻尼;
	float32					m_悬挂压缩;

	float32					m_轮胎摩擦;
	float32					m_旋转影响;



	E_车轮ID				m_安放方位;
	S_物理体* m_车轮物理体;
}S_粒子映射;





S_物体* f_phy_get粒子物体对象(S_Object* 物理体);

Inline uvec2 f_phy_get物体体粒子区间(S_Object* 物理体) {
	return (((S_物理体*)物理体))->m_粒子偏移和数量;
}

